from django.db import models
from sync.models.sf_object import SFObject
from django.db.models import Q
from django.db import connection, transaction

DEF_SF_FIELDS=['Id',
               'IsDeleted',
               'CreatedById',
               'LastModifiedById',
               'LastModifiedDate',
               'ParentId'
                ]
DEF_LOCAL_FIELDS=[('lid','pkey',11),
            ('lupdate','boolean',1),
            ('ldelete','boolean',1),
            ('ladd','boolean',1),
            ('lchange','dateTime',1),
            ('local_user','int',11),
            ]

class SFField(models.Model):
    obj=models.ForeignKey(SFObject)
    autoNumber = models.BooleanField() 
    byteLength = models.IntegerField(null=True)  
    calculated = models.BooleanField() 
    caseSensitive = models.BooleanField() 
    createable = models.BooleanField() 
    custom = models.BooleanField() 
    defaultedOnCreate = models.BooleanField() 
    deprecatedAndHidden = models.BooleanField() 
    digits = models.IntegerField(null=True)   
    filterable = models.BooleanField() 
    groupable = models.BooleanField() 
    idLookup = models.BooleanField() 
    label =  models.CharField(max_length=255,null=True)
    length = models.IntegerField(null=True)   
    name =  models.CharField(max_length=255)
    nameField = models.BooleanField() 
    namePointing = models.BooleanField() 
    nillable = models.BooleanField() 
    precision = models.IntegerField(null=True) 
    picklistValues = models.BooleanField()
    restrictedPicklist = models.BooleanField() 
    scale = models.IntegerField(null=True)   
    soapType =  models.CharField(max_length=255,null=True)
    sortable = models.BooleanField() 
    unique = models.BooleanField() 
    updateable = models.BooleanField()

    is_local = models.BooleanField() 
    is_sf = models.BooleanField(default=True) 
    is_default = models.BooleanField() 

    local_field=models.CharField(max_length=255,null=True,blank=True)
    local_type=models.CharField(max_length=55,null=True,blank=True)
    local_length=models.IntegerField(default=0)
    is_app=models.BooleanField()
    
    class Meta:
        db_table = 'sync_fields'
        app_label = 'sync'
    @staticmethod
    def set_field(sf_object,f):
        name=getattr(f,'name', "")
        created=False
        try:
            fld=SFField.objects.get(obj=sf_object,name=name)
        except:
            fld=SFField(obj=sf_object,name=name)
            created=True
        fld.autoNumber = getattr(f,'autoNumber', False) 
        fld.byteLength = getattr(f,'byteLength',None) 
        fld.calculated = getattr(f,'calculated', False) 
        fld.caseSensitive = getattr(f,'caseSensitive', False) 
        fld.createable = getattr(f,'createable', False) 
        fld.custom = getattr(f,'custom', False) 
        fld.defaultedOnCreate = getattr(f,'defaultedOnCreate', False) 
        fld.depfatedAndHidden = getattr(f,'depfatedAndHidden', False) 
        fld.digits = getattr(f,'digits',None)  
        fld.filterable = getattr(f,'filterable', False) 
        fld.groupable = getattr(f,'groupable', False) 
        fld.idLookup = getattr(f,'idLookup', False) 
        fld.label =  getattr(f,'label',"")
        fld.length = getattr(f,'length',None)  
        fld.nameField = getattr(f,'nameField', False) 
        fld.namePointing = getattr(f,'namePointing', False) 
        fld.nillable = getattr(f,'nillable', True) 
        fld.precision = getattr(f,'precision',None)  
        fld.restrictedPicklist = getattr(f,'restrictedPicklist', False) 
        fld.scale = getattr(f,'scale',None)  
        fld.soapType =  getattr(f,'soapType',"")
        fld.sortable = getattr(f,'sortable', False) 
        fld.unique = getattr(f,'unique', False) 
        fld.updateable = getattr(f,'updateable', False)
        if hasattr(f,'picklistValues'):
            fld.picklistValues = True
        fld.is_sf=True
        if name in DEF_SF_FIELDS:
            fld.is_default
            fld.set_local_fld()
       
        fld.save()
        return created
    @staticmethod
    def set_default_field(obj):
        for d in DEF_LOCAL_FIELDS:
            try:
                f=SFField.object.get(obj=obj,local_field=d[0])
            except:
                f=SFField(obj=obj,local_field=d[0])
            f.local_type=d[1]
            f.local_length=d[2]
            f.is_sf=False
            f.is_default=True
            f.save()
    def set_local_fld(self):
        self.local_type=self.get_local_type()
        self.local_length=self.byteLength
        self.local_field=self.name
        self.is_local=True
    def get_local_type(self):
        ftype=self.soapType.split(":")[1]
        if ftype=="string":
            if self.byteLength>255:
                return "text"
            else:
                return "varchar"
        elif ftype=="ID":
            return 'char'
        elif ftype=="base64Binary":
            return 'varbinary'
        else:
            return ftype
        
    def get_create_sql(self):
        if self.local_type=="text":
            return " %s text NULL "%self.local_field
        if self.local_type=="boolean":
            return " %s tinyint(1) DEFAULT NULL "%self.local_field
        if self.local_type=="date":
            return " %s date DEFAULT NULL "%self.local_field
        if self.local_type=="dateTime":
            return " %s datetime DEFAULT NULL "%self.local_field
        if self.local_type=="pkey":
            return " %s int(11) NOT NULL AUTO_INCREMENT, PRIMARY KEY ( %s ) "%(self.local_field,self.local_field)
        if self.local_type=="double":
            return " %s double  DEFAULT NULL "%self.local_field
        if self.local_type=="varbinary":
            return " %s varbinary(3000)  DEFAULT '' "%self.local_field
        else:
            return " %s  %s (%d) DEFAULT NULL "%(self.local_field,
                                              self.local_type,
                                              self.local_length)
    def remove_t(self):
        if self.is_local:
            if self.local_field:
                sql="ALTER TABLE %s DROP %s"%(self.obj.local_table,self.local_field)
                cursor=connection.cursor()
                cursor.execute(sql) 
                self.is_local=False
                self.save()
    def add_t(self):
        if not self.is_local:
            self.set_local_fld()
            sql="ALTER TABLE %s ADD %s"%(self.obj.local_table,self.get_create_sql())
            cursor=connection.cursor()
            cursor.execute(sql) 
            self.is_local=False
            self.save()
    def get_alter_sql_change(self):
        return " CHANGE %s %s"%(self.local_field,self.get_create_sql())
    def get_alter_sql_add(self):
        return " ADD %s "%(self.get_create_sql())
    def is_altered(self):
        pass
    @staticmethod
    def get_add_fields(obj):
        return SFField.objects.filter(obj=obj,is_default=False)
    @staticmethod
    def get_edit_fields(obj):
        return SFField.objects.filter(obj=obj,is_default=False,is_local=True)
    @staticmethod
    def get_picklist_fields(obj):
        pl_list=SFField.objects.filter(obj=obj,picklistValues=True,is_local=True)
        ret=[]
        for f in pl_list:
            ret.append(f.name)
        return ret
    def is_mandatory(self):
        if self.name=="Id":
            return True
        else:
            return False
